package cn.xorange.commons.datasource.configuration;

import cn.xorange.commons.data.configuration.GlobalDataConfig;
import cn.xorange.commons.data.constants.FieldConstants;
import cn.xorange.commons.data.handler.MyBatisPlusDataFillHandle;
import cn.xorange.commons.datasource.service.MyBatisMapWrapperFactory;
import cn.xorange.commons.utils.lang.ObjectUtils;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;


import javax.annotation.Resource;
import java.util.List;


/**
 * @author : yangjian
 * date : 2024/12/9
 * description :
 */
@Slf4j
@Configuration
@AutoConfigureBefore({MybatisAutoConfiguration.class})
@MapperScan(value = {
        "**.mapper"
})
public class MyBatisPlusConfig {

    @Resource
    MyBatisProperties properties;
    @Resource
    GlobalDataConfig config;

    /** 其他拓展拦截器 */
    @Autowired(required = false)
    private List<InnerInterceptor> additionalInterceptors;

    public static final String[] FILL_INSERT_FIELDS = {"tenantId","createById","createBy","createTime","parentId","treeNode"};

    public static final String[] FILL_UPDATE_FIELDS = {"updateById","updateBy","updateTime"};

    @Bean
    @ConfigurationProperties("mybatis.configuration")
    public MybatisConfiguration defaultMyBatisConfig(){
        MybatisConfiguration configuration = new MybatisConfiguration();
        //实体类至数据库转下划线
        configuration.setMapUnderscoreToCamelCase(properties.mapUnderscoreToCamelCase);
        configuration.setCallSettersOnNulls(true);
        configuration.setReturnInstanceForEmptyRow(true);
        configuration.setUseGeneratedShortKey(true);
        configuration.setLogImpl(StdOutImpl.class); //打印sql
        log.debug("Initializing [defaultMyBatisConfig]");
        return configuration;
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

        if (additionalInterceptors != null) {
            additionalInterceptors.forEach(interceptor::addInnerInterceptor);
        }
        // 分页配置
        //interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }

    private GlobalConfig.DbConfig dbConfig(){
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        dbConfig.setLogicDeleteField(FieldConstants.LOGIC_DEL);
        dbConfig.setLogicDeleteValue(ObjectUtils.toString(this.config.getLogicDeleteValue()));
        dbConfig.setLogicNotDeleteValue(ObjectUtils.toString(this.config.getLogicNotDeleteValue()));
        return dbConfig;
    }

    /***
     * 自定义会话工厂
     * @return :自定义的会话工厂
     */
    @Primary
    @Bean
    @ConditionalOnMissingBean
    public MybatisSqlSessionFactoryBean sqlSessionFactory() {
        /**
         String typeAliasesPackage = env.getFieldName("mybatis.typeAliasesPackage");
         typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
         VFS.addImplClass(SpringBootVFS.class);
         **/
        /** org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration.class */
        final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(properties.dataSourceConfig.dynamicDataSource());
        /** sessionFactory.setTypeAliasesPackage(typeAliasesPackage); **/
        //
        sessionFactory.setConfiguration(defaultMyBatisConfig());
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setDbConfig(this.dbConfig());
        // 自定义sql注入
        globalConfig.setSqlInjector(new CustomSqlInjector());
        globalConfig.setMetaObjectHandler(new MyBatisPlusDataFillHandle());
        sessionFactory.setGlobalConfig(globalConfig);
        sessionFactory.setObjectWrapperFactory(new MyBatisMapWrapperFactory());
        String mappers = properties.mapperLocations;
        //if (mappers.isEmpty()){
        //    mappers = DataDefaultConstants.MYBATIS_MAPPER_LOCATIONS;
        //}
        sessionFactory.setMapperLocations(properties.resolveMapperLocations(mappers.split(",") ));

        log.debug("Initializing [sqlSessionFactory]");
        return sessionFactory;
    }
}
